home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / inventor / SpaceballViewer / MyColSlider.c++ < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  14.0 KB  |  561 lines

  1. /*
  2.  * Copyright (c) 1990-94 Silicon Graphics, Inc.
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and
  5.  * its documentation for any purpose is hereby granted without fee, provided
  6.  * that the name of Silicon Graphics may not be used in any advertising or
  7.  * publicity relating to the software without the specific, prior written
  8.  * permission of Silicon Graphics.
  9.  *
  10.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
  11.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
  12.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  13.  *
  14.  * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
  15.  * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
  16.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE
  17.  * POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN
  18.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  19.  */
  20. /*
  21.  * Copyright (C) 1990-93   Silicon Graphics, Inc.
  22.  *
  23.  _______________________________________________________________________
  24.  ______________  S I L I C O N   G R A P H I C S   I N C .  ____________
  25.  |
  26.  |   $Revision: 1.1014 $
  27.  |
  28.  |   Classes:
  29.  |    MyColorSlider
  30.  |
  31.  |   Author(s)    : Alain Dumesny
  32.  |
  33.  ______________  S I L I C O N   G R A P H I C S   I N C .  ____________
  34.  _______________________________________________________________________
  35.  */
  36.  
  37. #ifdef DEBUG
  38. #include <stdio.h>
  39. #endif
  40. #include <malloc.h>
  41.  
  42. #include <X11/StringDefs.h>
  43. #include <X11/Intrinsic.h>
  44. #include <Xm/Text.h>
  45.  
  46. #include <Inventor/SbLinear.h>
  47. #include <Inventor/SbColor.h>
  48. #include "MyUIRegion.h"
  49. #include "MyColorSlider.h"
  50.  
  51. #include <GL/gl.h>
  52.  
  53. ////////////////////////////////////////////////////////////////////////
  54. //
  55. // Public constructor - build the widget right now
  56. //
  57. MyColorSlider::MyColorSlider(
  58.     Widget parent,
  59.     const char *name, 
  60.     SbBool buildInsideParent, 
  61.     MyColorSlider::Type type)
  62.     : MySlider(
  63.         parent,
  64.         name, 
  65.         buildInsideParent, 
  66.         FALSE) // tell slider not to build just yet  
  67. //
  68. ////////////////////////////////////////////////////////////////////////
  69. {
  70.     // In this case, this component is what the app wants, so buildNow = TRUE
  71.     constructorCommon(type, TRUE);
  72. }
  73.  
  74. ////////////////////////////////////////////////////////////////////////
  75. //
  76. // SoEXTENDER constructor - the subclass tells us whether to build or not
  77. //
  78. MyColorSlider::MyColorSlider(
  79.     Widget parent,
  80.     const char *name, 
  81.     SbBool buildInsideParent, 
  82.     MyColorSlider::Type type,
  83.     SbBool buildNow)
  84.     : MySlider(
  85.         parent,
  86.         name, 
  87.         buildInsideParent, 
  88.         FALSE) // tell slider not to build just yet  
  89. //
  90. ////////////////////////////////////////////////////////////////////////
  91. {
  92.     // In this case, this component may be what the app wants, 
  93.     // or it may want a subclass of this component. Pass along buildNow
  94.     // as it was passed to us.
  95.     constructorCommon(type, buildNow);
  96. }
  97.  
  98. ////////////////////////////////////////////////////////////////////////
  99. //
  100. // Called by the constructors
  101. //
  102. // private
  103. //
  104. void
  105. MyColorSlider::constructorCommon(MyColorSlider::Type t, SbBool buildNow)
  106. //
  107. //////////////////////////////////////////////////////////////////////
  108. {
  109.     // init local vars
  110.     WYSIWYGmode = FALSE;
  111.     type = t;
  112.     defaultColors = colors = NULL;
  113.     geometry = NULL;
  114.     color[0] = color[1] = color[2] = 0.0;
  115.     
  116.     // allocate memory for the color shading and geometry
  117.     switch(type) {
  118.     case RED_SLIDER: 
  119.     case GREEN_SLIDER: 
  120.     case BLUE_SLIDER:
  121.         colors = (SbColor *)malloc(2*sizeof(SbColor));
  122.         defaultColors = (SbColor *)malloc(2*sizeof(SbColor));
  123.         geometry = (SbVec2f *)malloc(4 * sizeof(SbVec2f));
  124.         break;
  125.     case HUE_SLIDER: 
  126.         colors = (SbColor *)malloc(7*sizeof(SbColor));
  127.         defaultColors = (SbColor *)malloc(7*sizeof(SbColor));
  128.         geometry = (SbVec2f *)malloc(14 * sizeof(SbVec2f));
  129.         break;
  130.     case SATURATION_SLIDER: 
  131.     case VALUE_SLIDER: 
  132.     case INTENSITY_SLIDER:
  133.         colors = (SbColor *)malloc(2*sizeof(SbColor));
  134.         defaultColors = colors; // since there is no fix default color
  135.         geometry = (SbVec2f *)malloc(4 * sizeof(SbVec2f));
  136.         break;
  137.     }
  138.     
  139.     // ??? reset the geometry to prevent the window manager under PI a362
  140.     // ??? to be killed (redrawing occurs even when window hasn't been
  141.     // ??? mapped yet so those values would be bogus)
  142.     int num = (type == HUE_SLIDER) ? 7 : 2;
  143.     for (int i=0; i<num; i++) {
  144.     geometry[2*i].setValue(0,0);
  145.     geometry[2*i+1].setValue(0,0);
  146.     }
  147.     
  148.     // now create the default colors
  149.     makeDefaultColors();
  150.     
  151.     // add a callback to update the slider's baseColor whenever the
  152.     // thumb is moved (unless it is INTENSITY_SLIDER, in which case
  153.     // the base color is independent).
  154.     if (type != INTENSITY_SLIDER)
  155.     addValueChangedCallback(MyColorSlider::sliderChangedCB, this);
  156.     
  157.     // Build the widget tree, and let SoXtComponent know about our base widget.
  158.     if (buildNow) {
  159.     Widget w = buildWidget(getParentWidget());
  160.     setBaseWidget(w);
  161.     }
  162. }
  163.  
  164.  
  165. ////////////////////////////////////////////////////////////////////////
  166. //
  167. //    Destructor.
  168. //
  169.  
  170. MyColorSlider::~MyColorSlider()
  171. //
  172. ////////////////////////////////////////////////////////////////////////
  173. {
  174.     // check to make sure colors and defaultColors are not the same
  175.     if (defaultColors != colors)
  176.         free(defaultColors);
  177.     free(colors);
  178.     free(geometry);
  179. }
  180.  
  181.  
  182. ////////////////////////////////////////////////////////////////////////
  183. //
  184. //    This routine is used to specify the slider top color, which is 
  185. //  reflected differently depending on the slider type.
  186. //
  187. // usage: public
  188.  
  189. void
  190. MyColorSlider::setBaseColor(
  191.     const float c[3])
  192. //
  193. ////////////////////////////////////////////////////////////////////////
  194. {
  195.     SbBool topChanged; // TRUE if the slider top region colors changed
  196.     float newVal = getValue();
  197.     
  198.     switch(type) {
  199.     
  200.     case RED_SLIDER: 
  201.     case HUE_SLIDER: 
  202.         topChanged = (WYSIWYGmode && (c[1]!=color[1] || c[2]!=color[2]));
  203.         newVal = c[0];
  204.         break;
  205.         
  206.     case GREEN_SLIDER: 
  207.         topChanged = (WYSIWYGmode && (c[0]!=color[0] || c[2]!=color[2]));
  208.         newVal = c[1];
  209.         break;
  210.         
  211.     case BLUE_SLIDER:
  212.         topChanged = (WYSIWYGmode && (c[0]!=color[0] || c[1]!=color[1]));
  213.         newVal = c[2];
  214.         break;
  215.         
  216.     case SATURATION_SLIDER:
  217.         topChanged = (c[0]!=color[0] || (WYSIWYGmode && c[2]!=color[2]));
  218.         newVal = c[1];
  219.         break;
  220.         
  221.     case VALUE_SLIDER:
  222.         topChanged = (c[0]!=color[0] || (WYSIWYGmode && c[1]!=color[1]));
  223.         newVal = c[2];
  224.         break;
  225.         
  226.     case INTENSITY_SLIDER: 
  227.         topChanged = (c[0]!=color[0] || c[1]!=color[1] || c[2]!=color[2]);
  228.         // thumb is independent of color for intensity sliders
  229.         break;
  230.     }
  231.     
  232.     // assign new color
  233.     color[0] = c[0];
  234.     color[1] = c[1];
  235.     color[2] = c[2];
  236.     
  237.     if (topChanged)
  238.     makeWYSIWYGcolors();
  239.     
  240.     // check for redraw needs
  241.     if (newVal != getValue())
  242.     setValue(newVal);
  243.     else if (topChanged) {
  244.     
  245.     // only redraw the top region of the slider
  246.     
  247.     if (! isVisible())
  248.         return;
  249.         glXMakeCurrent(getDisplay(), getNormalWindow(), getNormalContext());
  250.     drawSliderTopRegion();
  251.     }
  252. }
  253.  
  254.  
  255. ////////////////////////////////////////////////////////////////////////
  256. //
  257. //    This routine sets the WYSIWYG mode
  258. //
  259. // usage: public
  260.  
  261. void
  262. MyColorSlider::setWYSIWYG(SbBool flag)
  263. //
  264. ////////////////////////////////////////////////////////////////////////
  265. {
  266.     if (WYSIWYGmode == flag)
  267.     return;
  268.     
  269.     WYSIWYGmode = flag;
  270.     
  271.     // build WYSIWYG colors
  272.     if (WYSIWYGmode || type==SATURATION_SLIDER || type==VALUE_SLIDER)
  273.     makeWYSIWYGcolors();
  274.     
  275.     // only need to redraw top region
  276.     if (! isVisible())
  277.     return;
  278.     glXMakeCurrent(getDisplay(), getNormalWindow(), getNormalContext());
  279.     drawSliderTopRegion();
  280. }
  281.  
  282.  
  283. ////////////////////////////////////////////////////////////////////////
  284. //
  285. //    This routine is called when window has changed size
  286. //
  287. // usage: virtual protected
  288.  
  289. void
  290. MyColorSlider::sizeChanged(const SbVec2s &newSize)
  291. //
  292. ////////////////////////////////////////////////////////////////////////
  293. {
  294.     // first call base class routine
  295.     MySlider::sizeChanged(newSize);
  296.     
  297.     SbVec2f *v = geometry;
  298.     
  299.     // now recompute things that depend on window size
  300.     switch(type) {
  301.     case HUE_SLIDER:
  302.         {
  303.         // assign y values
  304.         for (int i=0; i<7; i++) {
  305.             (*(v++))[1] = sly1;
  306.             (*(v++))[1] = sly2 + 1;
  307.         }
  308.         
  309.         // assign x values
  310.         float l = (slx2 - slx1 + 1) / 6.0;
  311.         v = geometry;
  312.         (*(v++))[0] = slx1;
  313.         (*(v++))[0] = slx1;
  314.         for (i=1; i<6; i++) {
  315.             (*(v++))[0] = slx1 + i*l;
  316.             (*(v++))[0] = slx1 + i*l;
  317.         }
  318.         (*(v++))[0] = slx2 + 1;
  319.         (*v)[0] = slx2 + 1;
  320.         }
  321.         break;
  322.         
  323.     default:    // everything else
  324.         (*v)[0] = (*(v+1))[0] = slx1;
  325.         (*(v+2))[0] = (*(v+3))[0] = slx2 + 1;
  326.         (*v)[1] = (*(v+3))[1] = sly1;
  327.         (*(v+1))[1] = (*(v+2))[1] = sly2 + 1;
  328.         break; 
  329.     }
  330. }
  331.  
  332.  
  333. ////////////////////////////////////////////////////////////////////////
  334. //
  335. //    This routine draws the slider top region. It is called by the 
  336. //  MySlider::redraw routine.
  337. //
  338. // usage: virtual protected
  339.  
  340. void
  341. MyColorSlider::drawSliderTopRegion()
  342. //
  343. ////////////////////////////////////////////////////////////////////////
  344. {
  345.     SbColor *c = (WYSIWYGmode) ? colors : defaultColors;
  346.     SbVec2f *v = geometry;
  347.     
  348.     switch(type) {
  349.     case HUE_SLIDER:
  350.         {
  351.         glBegin(GL_QUAD_STRIP);
  352.         for (int i=0; i<7; i++) {
  353.             glColor3fv((c++)->getValue());
  354.             glVertex2fv((v++)->getValue());
  355.             glVertex2fv((v++)->getValue());
  356.         }
  357.         glEnd();
  358.         }
  359.         break;
  360.         
  361.     default:    // everything else!
  362.         glBegin(GL_POLYGON);
  363.         glColor3fv((c++)->getValue());
  364.         glVertex2fv((v++)->getValue());
  365.         glVertex2fv((v++)->getValue());
  366.         glColor3fv(c->getValue());
  367.         glVertex2fv((v++)->getValue());
  368.         glVertex2fv((v)->getValue());
  369.         glEnd();
  370.         break;
  371.         
  372.  
  373.     }
  374.     
  375.     drawThumbUIRegion(thumx1, thumy1, thumx2, thumy2);
  376. }
  377.  
  378.  
  379. ////////////////////////////////////////////////////////////////////////
  380. //
  381. //    Build the default colors (non WYSIWYG colors)
  382. //
  383. // usage: private
  384.  
  385. void
  386. MyColorSlider::makeDefaultColors()
  387. //
  388. ////////////////////////////////////////////////////////////////////////
  389. {
  390.     SbColor *c = defaultColors;
  391.     
  392.     switch(type) {
  393.     case RED_SLIDER:
  394.         (*c)[0] = (*c)[1] = (*c)[2] = 0.0; c++;
  395.         (*c)[0] = 1.0;
  396.         (*c)[1] = (*c)[2] = 0.0;
  397.         break;
  398.         
  399.     case GREEN_SLIDER:
  400.         (*c)[0] = (*c)[1] = (*c)[2] = 0.0; c++;
  401.         (*c)[0] = (*c)[2] = 0.0;
  402.         (*c)[1] = 1.0;
  403.         break;
  404.         
  405.     case BLUE_SLIDER:
  406.         (*c)[0] = (*c)[1] = (*c)[2] = 0.0; c++;
  407.         (*c)[0] = (*c)[1] = 0.0;
  408.         (*c)[2] = 1.0;
  409.         break;
  410.         
  411.     case HUE_SLIDER:
  412.         (*c)[0] = 1.0; (*c)[1] = (*c)[2] = 0.0; c++;
  413.         (*c)[0] = (*c)[1] = 1.0; (*c)[2] = 0.0; c++;
  414.         (*c)[0] = 0.0; (*c)[1] = 1.0; (*c)[2] = 0.0; c++;
  415.         (*c)[0] = 0.0; (*c)[1] = (*c)[2] = 1.0; c++;
  416.         (*c)[0] = (*c)[1] = 0.0; (*c)[2] = 1.0; c++;
  417.         (*c)[0] = 1.0; (*c)[1] = 0.0; (*c)[2] = 1.0; c++;
  418.         (*c)[0] = 1.0; (*c)[1] = (*c)[2] = 0.0;
  419.         break;
  420.         
  421.     case SATURATION_SLIDER:
  422.     case VALUE_SLIDER:
  423.     case INTENSITY_SLIDER:
  424.         c->setValue(0., 0., 0.); c++;   // black...
  425.         c->setValue(0., 0., 0.);        // to black (initially)
  426.         break;
  427.     }
  428. }
  429.  
  430.  
  431. ////////////////////////////////////////////////////////////////////////
  432. //
  433. //    builds the WYSIWYG colors.
  434. //
  435. // usage: private
  436.  
  437. void
  438. MyColorSlider::makeWYSIWYGcolors()
  439. //
  440. ////////////////////////////////////////////////////////////////////////
  441. {
  442.     SbColor *c = colors;
  443.     
  444.     switch(type) {
  445.     case RED_SLIDER: 
  446.         (*c)[0] = 0.0; (*(c+1))[0] = 1.0;
  447.         (*c)[1] = (*(c+1))[1] = color[1];
  448.         (*c)[2] = (*(c+1))[2] = color[2];
  449.         break;
  450.         
  451.     case GREEN_SLIDER: 
  452.         (*c)[0] = (*(c+1))[0] = color[0];
  453.         (*c)[1] = 0.0; (*(c+1))[1] = 1.0;
  454.         (*c)[2] = (*(c+1))[2] = color[2];
  455.         break;
  456.         
  457.     case BLUE_SLIDER:
  458.         (*c)[0] = (*(c+1))[0] = color[0];
  459.         (*c)[1] = (*(c+1))[1] = color[1];
  460.         (*c)[2] = 0.0; (*(c+1))[2] = 1.0;
  461.         break;
  462.         
  463.     case HUE_SLIDER: 
  464.         {
  465.         // convert to rgb
  466.         SbColor rgb;
  467.         rgb.setHSVValue(color);
  468.         
  469.         // get max and min values
  470.         float max = color[2]; 
  471.         float min = (rgb[0] < rgb[1]) ? 
  472.             ((rgb[0] < rgb[2]) ? rgb[0] : rgb[2]) : 
  473.             ((rgb[1] < rgb[2]) ? rgb[1] : rgb[2]);
  474.         
  475.         // now assign the 7 color ranges
  476.         (*c)[0] = max; (*c)[1] = (*c)[2] = min; c++;
  477.         (*c)[0] = (*c)[1] = max; (*c)[2] = min; c++;
  478.         (*c)[0] = min; (*c)[1] = max; (*c)[2] = min; c++;
  479.         (*c)[0] = min; (*c)[1] = (*c)[2] = max; c++;
  480.         (*c)[0] = (*c)[1] = min; (*c)[2] = max; c++;
  481.         (*c)[0] = max; (*c)[1] = min; (*c)[2] = max; c++;
  482.         (*c)[0] = max; (*c)[1] = (*c)[2] = min;
  483.         }
  484.         break;
  485.         
  486.     case SATURATION_SLIDER:
  487.         {
  488.         float val = (WYSIWYGmode) ? color[2] : 1.0;
  489.         
  490.         // find starting color (max value, grey)
  491.         (*c)[0] = (*c)[1] = (*c)[2] = val; c++;
  492.         
  493.         // find ending color
  494.         float hsv[3];
  495.         hsv[0] = color[0];
  496.         hsv[1] = 1.0;
  497.         hsv[2] = val;
  498.         c->setHSVValue(hsv);
  499.         }
  500.         break;
  501.         
  502.     case VALUE_SLIDER:
  503.         c++; // only change the 2nd color (the 1st is always black)
  504.         
  505.         // find ending color
  506.         if (color[1] == 0.0) {
  507.         (*c)[0] = (*c)[1] = (*c)[2] = 1.0;
  508.         }
  509.         else {
  510.         float hsv[3];
  511.         hsv[0] = color[0];
  512.         hsv[1] = (WYSIWYGmode) ? color[1] : 1.0;
  513.         hsv[2] = 1.0;
  514.         c->setHSVValue(hsv);
  515.         }
  516.         break;
  517.         
  518.     case INTENSITY_SLIDER:
  519.         c++; // only change the 2nd color (the 1st is always black)
  520.         *c = color;
  521.         break;
  522.     }
  523. }
  524.  
  525.  
  526.  
  527. //
  528. ////////////////////////////////////////////////////////////////////////
  529. // static callbacks stubs
  530. ////////////////////////////////////////////////////////////////////////
  531. //
  532.  
  533.  
  534. //
  535. // called whenever the slider value changes. Make sure the 
  536. // corresponding baseColor factor is also updated to reflect
  537. // the new slider position.
  538. //
  539. void
  540. MyColorSlider::sliderChangedCB(void *pt, float val)
  541. {
  542.     MyColorSlider *p = (MyColorSlider *)pt;
  543.     
  544.     switch(p->type) {
  545.     case RED_SLIDER: 
  546.     case HUE_SLIDER:
  547.         p->color[0] = val;
  548.         break;
  549.     case GREEN_SLIDER: 
  550.     case SATURATION_SLIDER: 
  551.         p->color[1] = val;
  552.         break;
  553.     case BLUE_SLIDER:
  554.     case VALUE_SLIDER: 
  555.         p->color[2] = val;
  556.         break;
  557.     case INTENSITY_SLIDER:
  558.         break; // nothing to do since thumnb is indep of baseColor
  559.     }
  560. }
  561.